﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using diploma.core.data.objects;

namespace diploma.core.data
{
    public enum ordering : byte
    {
        Asc = 0,
        Desc = 1
    }

    public class DataList<T> : IEnumerable
        where T : IDataObject
    {
        private List<T> dataObjects;
        private DataObjectTypes dataObjectType;
        public DataObjectTypes ObjectsType
        {
            get
            {
                return dataObjectType;
            }
        }

        public T this[int index]
        {
            get
            {
                return dataObjects[index];
            }
            set
            {
                Update(index, value);
            }
        }

        public int Count
        {
            get
            {
                return dataObjects.Count;
            }
        }

        public DataList(DataObjectTypes _dataObjectType)
        {
            dataObjectType = _dataObjectType;
            DataRouter.Instance.Act(DataActions.getAll, dataObjectType, null);
            dataObjects = new List<T>();
            switch (dataObjectType)
            {
                case DataObjectTypes.Question:
                    List<Question> qs = DataRouter.LastReturn as List<Question>;
                    foreach (IDataObject q in qs)
                    {
                        dataObjects.Add((T)q);
                    }
                    break;
                case DataObjectTypes.Term:
                    List<Term> tr = DataRouter.LastReturn as List<Term>;
                    foreach (IDataObject t in tr)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                case DataObjectTypes.Theme:
                    List<Theme> tm = DataRouter.LastReturn as List<Theme>;
                    foreach (IDataObject t in tm)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                case DataObjectTypes.Theorem:
                    List<Theorem> te = DataRouter.LastReturn as List<Theorem>;
                    foreach (IDataObject t in te)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                case DataObjectTypes.Statement:
                    List<Statement> st = DataRouter.LastReturn as List<Statement>;
                    foreach (IDataObject t in st)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                case DataObjectTypes.Problem: 
                    List<Problem> p = DataRouter.LastReturn as List<Problem>;
                    foreach (IDataObject t in p)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                case DataObjectTypes.Property:
                    List<Property> pp = DataRouter.LastReturn as List<Property>;
                    foreach (IDataObject t in pp)
                    {
                        dataObjects.Add((T)t);
                    }
                    break;
                default:
                     List<T> s = DataRouter.LastReturn as List<T>;
                     dataObjects = s;
                    break;
            }
        }

        public DataList()
        {
            dataObjects = new List<T>();
        }

        public void AddRange(IEnumerable<T> _dataObjects)
        {
            foreach (T tmp in _dataObjects)
            {
                Add(tmp);
            }
        }

        public void Add(T _dataObject)
        {
            DataRouter.Instance.Act(DataActions.insert, dataObjectType, _dataObject);
            if (dataObjects == null) dataObjects = new List<T>();
            T o = (T)DataRouter.LastReturn;
            if (o.Id != -1)
            {
                dataObjects.Add(o);
            }

        }

        public void Delete(long _id)
        {
            foreach (IDataObject item in dataObjects)
            {
                if (item.Id == _id)
                {
                    DataRouter.Instance.Act(DataActions.delete, dataObjectType, item);
                    dataObjects.Remove((T)item);
                    break;
                }
            }
        }

        public void Update(int _index, T _dataObject)
        {
            DataRouter.Instance.Act(DataActions.update, dataObjectType, _dataObject);
            dataObjects[_index] = _dataObject;
        }

        public void Sort()
        {
            dataObjects.Sort();
        }

        public void Sort(ordering order)
        {
            dataObjects.Sort();
            if (order == ordering.Desc)
            {
                dataObjects.Reverse();
            }
        }

        public T GetObjectById(long _id)
        {
            foreach (T t in dataObjects)
            {
                if (t.Id == _id)
                {
                    return t;
                }
            }
            T tmp = (T)(IDataObject)null;
            return tmp;

        }

        public void Reverse()
        {
            dataObjects.Reverse();
        }

        public int BinnarySearch(T _item)
        {
            return dataObjects.BinarySearch(_item);
        }

        public T[] ToArray()
        {
            return dataObjects.ToArray();
        }

        public List<T> ToList()
        {
            return dataObjects;
        }

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return dataObjects.GetEnumerator();
        }

        #endregion
    }
}
